package com.aplink.generic.adapter;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Locale;

import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.aplink.generic.GenericFragment;
import com.aplink.generic.constant.type.ColumnType;
import com.aplink.generic.pojo.ColumnSetting;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.controlspec.menu.PopupMenuSpec;
import com.aplink.generic.util.DateTimeUtils;
import com.aplink.generic.util.LogUtil;
import com.aplink.generic.util.ResourcesHelper;
import com.aplink.generic.widgets.ApLinkPopupMenu;

public class ConfigAdapter extends BaseAdapter {

    static class ViewHolder {
        public ArrayList<View> views;

        public ViewHolder() {
            this.views = new ArrayList<View>();
        }
    }

    private ArrayList<ColumnSetting> mColumnSettingList = new ArrayList<ColumnSetting>();
    private final Context mContext;
    private ArrayList<GenericObject> mDisplayObjects;
    private GenericFragment mGenericFragment;
    private final String mLayoutSrc;
    private int mLayoutsrcID;

    private ArrayList<GenericObject> mOriginalObjects;

    public ConfigAdapter() {
        this.mContext = null;
        this.mOriginalObjects = null;
        this.mColumnSettingList = null;
        this.mLayoutSrc = "";
    }

    /**
     * How to use this class, mAdapter = new
     * GenericConfigAdapter(getApplicationContext
     * (),genericObjectList,columnSettingList,"redeem_item_config"); Please
     * remember that each row in this list is plugged its tag with its own
     * object Therefore in detail page we just extract the object and parse as
     * you want
     * 
     * @param mContext
     * @param objects
     * @param columnSettings
     * @param layoutsrc
     */
    public ConfigAdapter(final GenericFragment genericFragment,
            final ArrayList<GenericObject> objects,
            final ArrayList<ColumnSetting> columnSettings, final int layoutsrc) {
        this.mGenericFragment = genericFragment;
        this.mContext = this.mGenericFragment.getApplicationContext();
        this.mOriginalObjects = objects;
        this.mDisplayObjects = objects;
        this.mColumnSettingList = columnSettings;
        this.mLayoutsrcID = layoutsrc;
        mLayoutSrc = null;
    }

    /**
     * How to use this class, mAdapter = new
     * GenericConfigAdapter(getApplicationContext
     * (),genericObjectList,columnSettingList,"redeem_item_config"); Please
     * remember that each row in this list is plugged its tag with its own
     * object Therefore in detail page we just extract the object and parse as
     * you want
     * 
     * @param mContext
     * @param objects
     * @param columnSettings
     * @param layoutsrc
     */
    public ConfigAdapter(final GenericFragment genericFragment,
            final ArrayList<GenericObject> objects,
            final ArrayList<ColumnSetting> columnSettings,
            final String layoutsrc) {
        this.mGenericFragment = genericFragment;
        this.mContext = this.mGenericFragment.getApplicationContext();
        this.mOriginalObjects = objects;
        this.mDisplayObjects = objects;
        this.mColumnSettingList = columnSettings;
        this.mLayoutSrc = layoutsrc;
    }

    @Override
    public int getCount() {
        return this.mDisplayObjects.size();
    }

    public ArrayList<GenericObject> getDisplayObjects() {
        return this.mDisplayObjects;
    }

    public Filter getFilter(final ArrayList<String> searchFileds) {
        final Filterable filterable = new Filterable() {

            @Override
            public Filter getFilter() {
                return new AdapterFilter(searchFileds, ConfigAdapter.this);
            }
        };

        return filterable.getFilter();
    }

    @Override
    public Object getItem(final int position) {
        return position;
    }

    @Override
    public long getItemId(final int position) {
        return position;
    }

    public final ArrayList<GenericObject> getOriginalObjects() {
        return mOriginalObjects;
    }

    @Override
    public View getView(final int position, final View convertView,
            final ViewGroup parent) {
        View row = convertView;
        if (row == null) {
            final LayoutInflater vi = (LayoutInflater) this.mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if (mLayoutSrc != null) {
                final int idLayout = ResourcesHelper
                        .getLayoutIdByName(this.mLayoutSrc);
                row = vi.inflate(idLayout, null, true);
            } else {
                row = vi.inflate(mLayoutsrcID, null);
            }
            final ViewHolder viewHolder = new ViewHolder();
            for (final ColumnSetting columnSetting : this.mColumnSettingList) {
                final String controlName = columnSetting.getLinkMappingName();
                if (!controlName.isEmpty()) {
                    final int idControl = ResourcesHelper
                            .getViewIdByName(controlName);
                    if (idControl == ResourcesHelper.RESOURCE_NOT_FOUND) {
                        continue;
                    }
                    final View view = row.findViewById(idControl);
                    view.setTag(columnSetting);
                    viewHolder.views.add(view);
                }
            }
            row.setTag(viewHolder);
        }
        final GenericObject object = this.mDisplayObjects.get(position);
        if (object == null) {
            return null;
        }
        final ViewHolder holder = (ViewHolder) row.getTag();
        for (final View view : holder.views) {
            final ColumnSetting columnSetting = (ColumnSetting) view.getTag();
            final ColumnType columnType = columnSetting.getColType();
            final String columnName = columnSetting.getColumnName();
            String columnValue = "";
            if (!TextUtils.isEmpty(object.getValue(columnName))) {
                columnValue = object.getValue(columnName).toString();
            } else if (columnSetting.isStaicResource()) {
                if (object.containsKey(ColumnSetting.STATIC_RESOURCE)
                        && (object.getValue(ColumnSetting.STATIC_RESOURCE) != null)) {
                    columnValue = object
                            .getValue(ColumnSetting.STATIC_RESOURCE).toString();
                } else {
                    columnValue = "";
                }
            }
            if (columnSetting.hasValueList()) {
                columnValue = columnSetting.getValueList().get(
                        columnValue.toUpperCase(Locale.getDefault()));
                if (columnValue == null) {
                    columnValue = columnSetting.getValueList().get(
                            columnSetting.getValueList().getDefaultValue()
                                    .toUpperCase(Locale.getDefault()));
                }
            }
            if (columnType.equals(ColumnType.ContextMenu)) {
                final PopupMenuSpec popupMenuSpec = columnSetting
                        .getPopupMenuSpec();
                final ApLinkPopupMenu customPopupMenu = new ApLinkPopupMenu(
                        this.mGenericFragment, popupMenuSpec, view);
                customPopupMenu.setGenericObject(object);
                customPopupMenu.initView();
            } else {
                if (view instanceof ImageView) {
                    final String content = object.getValue(
                            columnSetting.getColumnName()).toString();
                    handleImageView((ImageView) view, columnSetting, content);
                } else if (view instanceof TextView) {
                    String content = "";
                    if (columnType.equals(ColumnType.DateTime)) {
                        try {
                            final long miliseconds = Long
                                    .parseLong(columnValue);
                            if (TextUtils.isEmpty(columnSetting.getFormat())) {
                                content = DateTimeUtils.getDateTime(
                                        miliseconds, null);
                            } else {
                                content = DateTimeUtils.getDateTime(
                                        miliseconds, columnSetting.getFormat());
                            }
                        } catch (final NumberFormatException e) {
                            LogUtil.error(e.getMessage(), "getView", getClass()
                                    .getSimpleName());
                        } catch (final ParseException e) {
                            LogUtil.error(e.getMessage(), "getView", getClass()
                                    .getSimpleName());
                        }
                    } else if (columnType.equals(ColumnType.Text)) {
                        content = columnValue;
                    } else if (columnType.equals(ColumnType.Money)) {
                        final Double number = Double.valueOf(columnValue);
                        final DecimalFormat dec = new DecimalFormat(
                                columnSetting.getFormat());
                        content = dec.format(number);
                    }
                    ((TextView) view).setText(content);
                }
            }
        }
        return row;
    }

    private void handleImageView(final ImageView imageView,
            final ColumnSetting columnSetting, final String imageFile) {
    }

    public final void setDisplayObjects(
            final ArrayList<GenericObject> displayObjects) {
        mDisplayObjects = displayObjects;
    }

    public void setDisplayResult(final ArrayList<GenericObject> displayResult) {
        this.mDisplayObjects = displayResult;
        this.mOriginalObjects = displayResult;
        notifyDataSetChanged();
    }
}
